﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;

namespace Com.Lancetinc.Evs.WpfTools
{
    public class ExtendedTextBoxColumn : DataGridTextColumn
    {
        #region Properties

        #region TextAlignment
        protected TextAlignment GetTextAlignment()
        {
            switch (HorizontalAlignment)
            {
                case HorizontalAlignment.Center:
                    return TextAlignment.Center;
                case HorizontalAlignment.Left:
                    return TextAlignment.Left;
                case HorizontalAlignment.Right:
                    return TextAlignment.Right;
                case HorizontalAlignment.Stretch:
                    return TextAlignment.Justify;
                default:
                    throw new ArgumentOutOfRangeException("HorizontalAlignment", "Unsupported alignment type!");
            }
        }

        #endregion Implementation

        #region TextWrapping Property

        public TextWrapping TextWrapping
        {
            get => (TextWrapping)GetValue(TextWrappingProperty);
            set => SetValue(TextWrappingProperty, value);
        }

        public static readonly DependencyProperty TextWrappingProperty =
            DependencyProperty.Register(
                "TextWrapping",
                typeof(TextWrapping),
                typeof(ExtendedTextBoxColumn),
                new UIPropertyMetadata(TextWrapping.NoWrap));

        #endregion TextWrapping Property

        #region TextTrimming Property

        public TextTrimming TextTrimming
        {
            get => (TextTrimming)GetValue(TextTrimmingProperty);
            set => SetValue(TextTrimmingProperty, value);
        }

        public static readonly DependencyProperty TextTrimmingProperty =
            DependencyProperty.Register(
                "TextTrimming",
                typeof(TextTrimming),
                typeof(ExtendedTextBoxColumn),
                new UIPropertyMetadata(TextTrimming.None));

        #endregion TextTrimming Property

        #region MaxLength Property

        /// <summary>
        /// 最大长度，默认为20
        /// </summary>
        public int MaxLength
        {
            get => (int)GetValue(MaxLengthProperty);
            set => SetValue(MaxLengthProperty, value);
        }

        public static readonly DependencyProperty MaxLengthProperty =
            DependencyProperty.Register(
                "MaxLength",
                typeof(int),
                typeof(ExtendedTextBoxColumn),
                new UIPropertyMetadata(20));

        #endregion MaxLength Property

        #region Padding Property

        /// <summary>
        /// Padding
        /// </summary>
        public Thickness Padding
        {
            get => (Thickness)GetValue(PaddingProperty);
            set => SetValue(PaddingProperty, value);
        }

        public static readonly DependencyProperty PaddingProperty =
            DependencyProperty.Register(
                "Padding",
                typeof(Thickness),
                typeof(ExtendedTextBoxColumn),
                new UIPropertyMetadata(new Thickness(0)));

        #endregion MaxLength Property

        #region ColumnVisibility Property

        /// <summary>
        /// 最大长度，默认为20
        /// </summary>
        public Visibility ColumnVisibility
        {
            get => (Visibility)GetValue(ColumnVisibilityProperty);
            set => SetValue(ColumnVisibilityProperty, value);
        }

        public static readonly DependencyProperty ColumnVisibilityProperty =
            DependencyProperty.Register(
                "ColumnVisibility",
                typeof(Visibility),
                typeof(ExtendedTextBoxColumn),
                new UIPropertyMetadata(Visibility.Visible));

        #endregion ColumnVisibility Property

        #region HorizontalAlignment Property

        public HorizontalAlignment HorizontalAlignment
        {
            get => (HorizontalAlignment)GetValue(HorizontalAlignmentProperty);
            set => SetValue(HorizontalAlignmentProperty, value);
        }

        public static readonly DependencyProperty HorizontalAlignmentProperty =
            DependencyProperty.Register(
                "HorizontalAlignment",
                typeof(HorizontalAlignment),
                typeof(ExtendedTextBoxColumn),
                new UIPropertyMetadata(HorizontalAlignment.Stretch));

        #endregion HorizontalAlignment Property

        #region VerticalAlignment Property

        public VerticalAlignment VerticalAlignment
        {
            get => (VerticalAlignment)GetValue(VerticalAlignmentProperty);
            set => SetValue(VerticalAlignmentProperty, value);
        }

        public static readonly DependencyProperty VerticalAlignmentProperty =
            DependencyProperty.Register(
                nameof(VerticalAlignment),
                typeof(VerticalAlignment),
                typeof(ExtendedTextBoxColumn),
                new UIPropertyMetadata(VerticalAlignment.Stretch));

        #endregion VerticalAlignment Property

        #region IsInputMethodEnabled Property

        public bool IsInputMethodEnabled
        {
            get => (bool)GetValue(IsInputMethodEnabledProperty);
            set => SetValue(IsInputMethodEnabledProperty, value);
        }

        public static readonly DependencyProperty IsInputMethodEnabledProperty =
            DependencyProperty.Register(
                nameof(IsInputMethodEnabled),
                typeof(bool),
                typeof(ExtendedTextBoxColumn),
                new UIPropertyMetadata(true));

        #endregion

        #region IsShowToolTip Property

        public bool IsShowToolTip
        {
            get => (bool)GetValue(IsShowToolTipProperty);
            set => SetValue(IsShowToolTipProperty, value);
        }

        public static readonly DependencyProperty IsShowToolTipProperty =
            DependencyProperty.Register(
                nameof(IsShowToolTip),
                typeof(bool),
                typeof(ExtendedTextBoxColumn),
                new UIPropertyMetadata(false));

        #endregion

        #endregion Properties

        #region DataGridTextColumn overrides

        protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
        {
            var element = base.GenerateElement(cell, dataItem);

            ((TextBlock)element).TextWrapping = TextWrapping;
            ((TextBlock)element).TextTrimming = TextTrimming;
            ((TextBlock)element).Padding = Padding;

            element.HorizontalAlignment = HorizontalAlignment;
            element.VerticalAlignment = VerticalAlignment;
            element.Visibility = ColumnVisibility;

            if (IsShowToolTip && Binding != null)
            {
                BindingOperations.SetBinding(element, FrameworkElement.ToolTipProperty, Binding);
            }

            return element;
        }

        protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
        {
            var textBox = (TextBox)base.GenerateEditingElement(cell, dataItem);

            var style = (Style)textBox.FindResource("LrDefaultTextBoxForDataGrid");
            if (style != null)
            {
                textBox.Style = style;
            }

            textBox.MaxLength = MaxLength;
            textBox.TextWrapping = TextWrapping;
            textBox.TextAlignment = GetTextAlignment();
            textBox.VerticalContentAlignment = VerticalAlignment;
            textBox.Visibility = ColumnVisibility;

            if (!IsInputMethodEnabled) // 输入法
                InputMethod.SetIsInputMethodEnabled(textBox, false);

            return textBox;
        }

        #endregion DataGridTextColumn overrides

        protected void SyncProperties(FrameworkElement e)
        {
            SyncColumnProperty(this, e, TextElement.FontFamilyProperty, FontFamilyProperty);
            SyncColumnProperty(this, e, TextElement.FontSizeProperty, FontSizeProperty);
            SyncColumnProperty(this, e, TextElement.FontStyleProperty, FontStyleProperty);
            SyncColumnProperty(this, e, TextElement.FontWeightProperty, FontWeightProperty);
            SyncColumnProperty(this, e, TextElement.ForegroundProperty, ForegroundProperty);

            if (e is TextBlock)
            {
                SyncColumnProperty(this, e, TextBlock.TextWrappingProperty, TextWrappingProperty);
                SyncColumnProperty(this, e, TextBlock.TextTrimmingProperty, TextTrimmingProperty);
                SyncColumnProperty(this, e, TextBlock.PaddingProperty, PaddingProperty);
            }
        }

        private static void SyncColumnProperty(DependencyObject column, DependencyObject content, DependencyProperty contentProperty, DependencyProperty columnProperty)
        {
            if (IsDefaultValue(column, columnProperty))
            {
                content.ClearValue(contentProperty);
            }
            else
            {
                content.SetValue(contentProperty, column.GetValue(columnProperty));
            }
        }

        private static bool IsDefaultValue(DependencyObject d, DependencyProperty dp)
        {
            return DependencyPropertyHelper.GetValueSource(d, dp).BaseValueSource == BaseValueSource.Default;
        }
    }
}
